#pragma once 
#include <iostream>
#include <fstream>
#include <string>
#include<algorithm>
#include <vector>
#include <ctime>
#include <filesystem>
#include <set>
#include <map>
#include <variant>

#include "GeneralMethod.h"

using namespace std;

#define M_PI 3.1415926535

//单元相关
const vector<string> nastran_type{ "CONM2", "CELAS1", "CELAS2", "CBEAM", "CBUSH", "CBUSH1D", "CROD", "CGAP",
								  "CBAR", "CTETRA", "CPYRAM", "CPYRA", "CPENTA", "CHEXA", "CTRIAR","CTRIA3",
								  "CTRAX6", "CTRIAX6", "CTRIA6", "CQUADR", "CSHEAR", "CQUAD4", "CQUAD8", };

inline std::map<string, string> nastran_type_to_meshio_type =
{   std::make_pair("CONM2","vertex"),
	std::make_pair("CELAS1","line"),
	std::make_pair("CELAS2","line"),
	std::make_pair("CBEAM","line"),
	std::make_pair("CBUSH","line"),
	std::make_pair("CBUSH1D","line"),
	std::make_pair("CROD","line"),
	std::make_pair("CGAP","line"),
	std::make_pair("CBAR","line"),
	std::make_pair("CTETRA","tetra"),
	std::make_pair("CPYRAM",""),
	std::make_pair("CPYRA",""),
	std::make_pair("CPENTA","wedge"),
	std::make_pair("CHEXA","hexahedron"),
	std::make_pair("CTRIAR","triangle"),
	std::make_pair("CTRIA3","triangle"),
	std::make_pair("CTRAX6","triangle6"),
	std::make_pair("CTRIAX6","triangle6"),
	std::make_pair("CTRIA6","triangle6"),
	std::make_pair("CQUADR","quad"),
	std::make_pair("CSHEAR",""),
	std::make_pair("CQUAD4","quad"),
	std::make_pair("CQUAD8","quad8"),





};
//节点相关
const vector<string> nodes_related_keywords = { "GRID", "CORD2R", "CORD2C","CORD1R","CORD1C" };
//坐标系相关
const vector<string> coord_related_keywords = { "CORD2C", "CORD2R","CORD1C", "CORD1R" };

class ReadBDF_
{
public:
	ReadBDF_(void) {
		set<string> temp_set;
		temp_set.insert(nastran_type.begin(), nastran_type.end());
		temp_set.insert(nodes_related_keywords.begin(), nodes_related_keywords.end());
		temp_set.insert(coord_related_keywords.begin(), coord_related_keywords.end());
		all_keywords.assign(temp_set.begin(), temp_set.end());
	};
	~ReadBDF_(void) {};
	static ReadBDF_* GetInst()
	{
		if (!_instance)
		{
			_instance = new ReadBDF_();
		}
		return _instance;
	};

public:
	void setReadFilePath(std::string path_) {
		read_file_path = path_;
	};
	void setWriteFilePath(std::string path_) {
		write_file_path = path_;
	};
	void setExeFilePath(std::string path_) {
		exe_path = path_;
	};
	void read_bdf_data();
	int write_gmsh_file();
	int write_vtk_file();
	int write_gmsh_file_from_vtk();
	std::vector<std::vector<float>>* get_nodes_coord() {return &nodes_coord;};
	std::map<int, std::vector<int>>* get_elements_points() { return &elements_points; };
	std::map<std::string, std::vector<int>>* get_elements_sequence() { return &elements_sequence; };
private:
	vector<string> all_keywords;
	vector<vector<vector<string>>> deal_all_packages_out;
	vector<string> not_recording_keywords;
	map<int, vector<int>> set_msg_map;

	std::vector <int> nodes_sequence;
	std::vector<std::vector<float>> nodes_coord;
	std::map<int, int> nodes_mapping_dict;/*old，new*/
	std::set<int> fluid_nodes;
	std::map<std::string, std::vector<int>> local_sys_for_spc;

	std::vector<std::string> elements_names;
	std::map<std::string, std::vector<int>> elements_sequence;
	std::map<int, std::vector<int>> elements_points;
	std::map<int, int> ele_mapping_dict;/*old，new*/

private:
	void read_all_keywords();
	void read_users_set();
	void read_nodes();
	void read_elements();
	void look_for_msg(vector<string>& all_packages);
	void split_and_combine(vector<string> dim1_list, vector<vector<string>>& deal_all_packages);
	void division(vector<vector<string>>& origin_data, vector<vector<string>>& dim2_list, vector<vector<vector<string>>>& result);
	vector<int> deal_thru(int node1, int  node2);
	vector<vector<variant<int, float, string>>> change_data_type(vector<vector<string >>& origin_data);
	vector<float> from_local_coord_sys_to_global_coord_sys(vector<float>& local_coord, vector<vector<float>>& local_coord_sys);
	vector<int> adjust_ids_vector(vector<int>& origin_data, map<int, int>& mapping_dict);
	int adjust_id(int& origin_data, map<int, int>& mapping_dict);
private:
	static ReadBDF_* _instance;
	std::string read_file_path;
	std::string write_file_path;
	std::string exe_path;
};

